#![allow(dead_code)]

#[derive(Debug)]
struct ReferenceLrn {}

impl ReferenceLrn {
    pub fn hello() {
        println!("Reference learning!");
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_reference() {
        use std::ptr;

        let five = 5;
        let other_five = 5;
        let five_ref = &five;
        let same_five_ref = &five;
        let other_five_ref = &other_five;

        // NOTE: == 比较两个引用的值是否相等
        // 引用的比较是值的比较
        assert_eq!(five_ref, same_five_ref);
        assert_eq!(five_ref, other_five_ref);
        // 自动解引用为值，内存地址并不相同
        assert_eq!(five_ref, other_five_ref);
        assert_eq!(five_ref, &5);
        assert_eq!(*five_ref, 5);
        println!("&5: {:p}", &5);
        // println!("size of five: {}", std::mem::size_of_val(&five));
        // println!("five_ref: {}", five_ref);
        println!("other_five_ref addr: {:p}", other_five_ref);
        println!("five_ref addr: {:p}", five_ref);
        // println!("size of five_ref: {}", std::mem::size_of_val(five_ref));
        // println!("other_five_ref: {:?}", other_five_ref);
        // println!("other_five_ref addr: {:p}", other_five_ref);
        // println!(
        //     "size of other_five_ref: {}",
        //     std::mem::size_of_val(other_five_ref)
        // );

        // NOTE: ptr::eq() 比较两个指针是否指向同一个内存地址
        assert!(ptr::eq(five_ref, same_five_ref));
        assert!(!ptr::eq(five_ref, other_five_ref));
    }

    #[test]
    #[allow(unused_variables)]
    fn test_ref_operator() {
        // NOTE: & 或&mut 应用于位置表达式，生成指向值所在的内存位置的引用（指针）
        // NOTE: & 或&mut 应用于值表达式上，则会创建一个临时值。
        let a = &&10;
        let b = &&&&mut 10;
        let c = &&&mut 12;

        println!("a addr: {:p}", a);
        let mut array = [-2, 3, 9];
        // NOTE: 当前作用域中，可变借用了array，那array只能通过mutable_ref来使用
        let mutable_ref = &mut array;
        // array[1] = 2;
        mutable_ref[0] = -4;

        println!("{:?}", array);
    }
}
